﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using VIA.Foundation;
using VIA.ImageProcessing;
using VIA.Integration.LeadShine.Presentation.Properties;
using VIA.Integration.Presentation;
using VIA.Presentation;
using VIA.RbacPassport;
namespace VIA.Integration.LeadShine.Presentation.ViewModel
{
    [ViewModel(typeof(IAxisView))]
    internal class AxisViewModel : EditorViewModel<IAxisView, AxisOption>
    {
        #region Fields
        ITypeAdapter _typeAdapter;

        protected IMessageService _messageService;
        protected IBusyService _busyService;
        protected IDispatcherService _dispatcherService;
        protected IShellService _shellService;
        protected IFileDialogService _dialogService;
        protected ILogger _logger;
        readonly ICurrentUser _currentUser;
        private IPermissionProvider _permissionProvider;
        private DmcAxis _axis;
        private WriteableBitmap _luminanceImageSource;
        private ImageData3DU imageData3DU;
        private AutoResetEvent _autoResetEvent = new(true);
        private CancellationTokenSource _cancellationTokenSource;
        private double currentPosition;
        private double currentSpeed;
        private bool isMoveEnabel = true;
        private bool isPositiveLimit;
        private bool isNegativeLimit;
        private bool isOriginalSensor;
        AxisModel _model;
        private bool isParamEnable;
        #endregion

        #region Commands

        public IRelayCommand CleanCommand { get; }
        public IRelayCommand CancelCommand { get; }
        #endregion

        #region Properties

        public DmcAxis Axis
        {
            get
            {
                return _axis;
            }
            set
            {
                if (SetProperty(ref _axis, value))
                {
                    var json = Settings.Default.AxisSettings;
                    var o = _currentRecipe.Get<AxisOption>(value.Id);
                    AxisDebugOption debugOption = new AxisDebugOption();
                    if (!json.IsNullOrEmpty())
                    {
                        var dic = JsonConvert.DeserializeObject<Dictionary<string, AxisDebugOption>>(json);
                        debugOption = dic.ContainsKey(value.Id) ? dic[value.Id] : new AxisDebugOption();
                    }
                    Model = new AxisModel(_axis, Option, _commandFactory, _typeAdapter, debugOption);
                }

            }
        }
        public AxisModel Model
        {
            get => _model;
            set => SetProperty(ref _model, value);
        }

        public bool IsParamEnable { get => isParamEnable; set => SetProperty(ref isParamEnable, value); }

        #endregion
        public AxisViewModel(IServiceProvider service) : base(service)
        {
            _typeAdapter = service.GetRequiredService<ITypeAdapter>();
            _messageService = service.GetRequiredService<IMessageService>();
            _busyService = service.GetRequiredService<IBusyService>();
            _dispatcherService = service.GetRequiredService<IDispatcherService>();
            _shellService = service.GetRequiredService<IShellService>();
            _dialogService = service.GetRequiredService<IFileDialogService>();
            _dialogService = service.GetRequiredService<IFileDialogService>();
            _logger = service.GetRequiredService<ILogger<AxisViewModel>>();
            _currentUser = service.GetService<ICurrentUser>();
            _permissionProvider = service.GetRequiredService<IPermissionProvider>();
            CleanCommand = _commandFactory.Create(Clean);
            CancelCommand = _commandFactory.Create(Cancel);
            _currentUser.UserChanged += CurrentUser_UserChanged;
        }

        private void CurrentUser_UserChanged(object? sender, UserChangedEventArgs e)
        {
            CheckIsParamEnable();
        }

        private  void CheckIsParamEnable()
        {
            _dispatcherService.Invoke(async () =>
            {
                var pms = _permissionProvider.Permissions().FirstOrDefault(x => x.Name == "轴参数设置");
                IsParamEnable = await _currentUser.IsGrantedAsync(pms);
                Model.IsParamEnable = IsParamEnable;
            });
        }

        private void Clean()
        {
            _cancellationTokenSource?.Cancel();
        }

        void Cancel()
        {
            this.View.Close();
        }


        private void InitializeView()
        {
            CheckIsParamEnable();
            _cancellationTokenSource = new CancellationTokenSource();
            Task.Factory.StartNew(() => Refresh(_cancellationTokenSource.Token));
        }
        public void Refresh(CancellationToken cancellationToken)
        {
            Task.Factory.StartNew(async () =>
            {
                while (!cancellationToken.IsCancellationRequested)
                {
                    _model.RefreshSates();
                    await Task.Delay(50);
                }
            }, _cancellationTokenSource.Token);
        }

        #region Fuction

        private void Close()
        {
            try
            {
                View.Close();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, ex.Message);
            }
        }
        protected override async Task Save()
        {
            Dictionary<string, AxisDebugOption> dic = JsonConvert.DeserializeObject<Dictionary<string, AxisDebugOption>>(Settings.Default.AxisSettings) ?? new Dictionary<string, AxisDebugOption>();
            dic[Axis.Id] = Model.DebugOption;
            Settings.Default.AxisSettings = JsonConvert.SerializeObject(dic);
            Settings.Default.Save();
            Option = _typeAdapter.Adapt<AxisOption>(Model);
            _currentRecipe.Set(Axis.Id, Option);
            //_axis.Option = Option;
            await _currentRecipe.SaveAsync().ConfigureAwait(continueOnCapturedContext: false);
            await _messageService.ShowMessageAsync(View, "保存参数成功");
        }

        protected override void OnEditObjectChanged(IObject oldObject, IObject newObject)
        {
            if (newObject is DmcAxis axis)
            {
                Axis = axis;
                InitializeView();
            }
        }
        #endregion
    }
}
